//
// * Copyright (c) 2002-2009 "Neo Technology,"
// *     Network Engine for Objects in Lund AB [http://neotechnology.com]
// *
// * This file is part of Neo4j.
// * 
// * Neo4j is free software: you can redistribute it and/or modify
// * it under the terms of the GNU Affero General Public License as
// * published by the Free Software Foundation, either version 3 of the
// * License, or (at your option) any later version.
// * 
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// * GNU Affero General Public License for more details.
// * 
// * You should have received a copy of the GNU Affero General Public License
// * along with this program. If not, see <http://www.gnu.org/licenses/>.
// 
namespace org.neo4j.kernel.impl.core
{


	using Direction = org.neo4j.graphdb.Direction;
	using Node = org.neo4j.graphdb.Node;
	using Relationship = org.neo4j.graphdb.Relationship;
	using ArrayIntSet = org.neo4j.kernel.impl.util.ArrayIntSet;

	internal class RelationshipArrayIntSetIterator : IEnumerable <Relationship>, IEnumerator <Relationship>
	{
		private Logger log = Logger.getLogger(typeof(RelationshipArrayIntSetIterator).Name);

		private IEnumerator <int> relIds;
		private Node fromNode;
		private Direction direction = null;
		private Relationship nextElement = null;
		private readonly NodeManager nodeManager;

		internal RelationshipArrayIntSetIterator(ArrayIntSet relIds, Node fromNode, Direction direction, NodeManager nodeManager)
		{
			this.relIds = relIds.GetEnumerator();
			this.fromNode = fromNode;
			this.direction = direction;
			this.nodeManager = nodeManager;
		}

		internal RelationshipArrayIntSetIterator(IEnumerator <int> relIds, Node fromNode, Direction direction, NodeManager nodeManager)
		{
			this.relIds = relIds;
			this.fromNode = fromNode;
			this.direction = direction;
			this.nodeManager = nodeManager;
		}

		public virtual IEnumerator <Relationship> iterator()
		{
			return new RelationshipArrayIntSetIterator(relIds, fromNode, direction, nodeManager);
		}

		public virtual bool hasNext()
		{
			if (nextElement != null)
			{
				return true;
			}
			do
			{
			// if ( nextPosition < relIds.length )
				if (relIds.MoveNext())
				{
					int nextId = relIds.Current;
					try
					{
						Relationship possibleElement = nodeManager.getRelationshipById(nextId);
						if (direction == Direction.INCOMING && possibleElement.getEndNode().Equals(fromNode))
						{
							nextElement = possibleElement;
						}
						else if (direction == Direction.OUTGOING && possibleElement.getStartNode().Equals(fromNode))
						{
							nextElement = possibleElement;
						}
						else if (direction == Direction.BOTH)
						{
							nextElement = possibleElement;
						}
					}
					catch (System.Exception t)
					{
						log.log(Level.FINE, "Unable to get relationship " + nextId, t);
					}
				}
			}
			while (nextElement == null && relIds.MoveNext());
			return nextElement != null;
		}

		public virtual Relationship next()
		{
			hasNext();
			if (nextElement != null)
			{
				Relationship elementToReturn = nextElement;
				nextElement = null;
				return elementToReturn;
			}
			throw new NoSuchElementException();
		}

		public virtual void remove()
		{
			throw new UnsupportedOperationException();
		}
	}

}